package com.ruoyi.web.controller.system;

import com.ruoyi.common.constant.CacheConstants;
import com.ruoyi.common.constant.Constants;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.domain.entity.SysMenu;
import com.ruoyi.common.core.domain.entity.SysUser;
import com.ruoyi.common.core.domain.model.LoginBody;
import com.ruoyi.common.core.domain.model.LoginUser;
import com.ruoyi.common.core.redis.RedisCache;
import com.ruoyi.common.exception.base.BaseException;
import com.ruoyi.common.exception.user.UserNotExistsException;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.framework.web.service.SysLoginService;
import com.ruoyi.framework.web.service.SysPermissionService;
import com.ruoyi.framework.web.service.TokenService;
import com.ruoyi.system.service.ISysMenuService;
import com.ruoyi.system.service.ISysRoleService;
import com.ruoyi.system.service.ISysUserService;
import com.ruoyi.system.utils.SendSms;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.security.PermitAll;
import javax.servlet.http.HttpServletRequest;
import java.util.*;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * 登录验证
 *
 * @author ruoyi
 */
@RestController
@Slf4j
public class SysLoginController {
    @Autowired
    private SysLoginService loginService;

    @Autowired
    private ISysMenuService menuService;

    @Autowired
    private SysPermissionService permissionService;

    @Autowired
    private TokenService tokenService;

    @Autowired
    private SendSms sendSms;

    @Autowired
    private RedisCache redisCache;

    @Autowired
    ISysUserService sysUserService;
    @Autowired
    ISysRoleService iSysRoleService;

    /**
     * 登录方法
     *
     * @param loginBody 登录信息
     * @return 结果
     */
    @PostMapping("/login")
    public AjaxResult login(@RequestBody LoginBody loginBody) {
        AjaxResult ajax = AjaxResult.success();
        String token = loginService.login(loginBody.getUsername(), loginBody.getPassword(), loginBody.getCode(),
                loginBody.getUuid());
        ajax.put(Constants.TOKEN, token);
        return ajax;
    }

    /**
     * 本人验证码校验
     *
     * @param loginBody
     * @return
     */
    @PermitAll
    @PostMapping("/prepareLogin")
    public AjaxResult prepareLogin(@RequestBody LoginBody loginBody, HttpServletRequest request) {
        loginService.validateCaptcha(loginBody.getUsername(), loginBody.getCode(), loginBody.getUuid());
        SysUser sysUser = sysUserService.selectUserByUserName(loginBody.getUsername());
        if (null == sysUser) {
            throw new BaseException("未查到该用户");
        }
        Map<String, Integer> responseMap = new HashMap();
        responseMap.put("tag", 200);
        List<Long> roleIds = iSysRoleService.selectRoleListByUserId(sysUser.getUserId());
        if (roleIds.contains(105L)) {
            responseMap.put("tag", 105);
        } else if (roleIds.contains(106L)) {
            if ("18602343785".equals(loginBody.getUsername())) {
            } else {
                String clientIp = getClientIp(request);
                if (StringUtils.isNotEmpty(clientIp)) {
                    if (clientIp.contains("113.204.47")) {
                        responseMap.put("tag", 200);
                    } else {
                        responseMap.put("tag", 106);
                    }
                }
            }
        } else if (roleIds.contains(107L)) {
            responseMap.put("tag", 107);
        } else if (roleIds.contains(109L)) {
            responseMap.put("tag", 109);
        }
        AjaxResult ajax = AjaxResult.success(responseMap);
        return ajax;
    }

    private String getClientIp(HttpServletRequest request) {
        String ip = request.getHeader("X-Forwarded-For");
        if (ip != null && !ip.isEmpty()) {
            ip = ip.split(",")[0].trim();
        }
        if (ip == null || ip.isEmpty() || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getRemoteAddr();
        }
        return ip;
    }

    /**
     * 领导验证码校验
     *
     * @param loginBody
     * @return
     */
    @PermitAll
    @PostMapping("/prepareLeaderLogin")
    public AjaxResult prepareLeaderLogin(@RequestBody LoginBody loginBody) {
        loginService.validateCaptcha(loginBody.getUsername(), loginBody.getCode(), loginBody.getUuid());
        AjaxResult ajax = AjaxResult.success();
        return ajax;
    }


    private int getCode() {
        Random random = new Random();
        int code = random.nextInt(9000) + 1000;
        return code;
    }

    private int getCode2() {
        Random random = new Random();
        int code = random.nextInt(900) + 100;
        return code;
    }


    @PermitAll
    @PostMapping("/getSmsCode2")
    public AjaxResult getSmsCode2(@RequestBody LoginBody loginBody) throws ExecutionException, InterruptedException {
        if (StringUtils.isEmpty(loginBody.getUsername())) {
            throw new BaseException("手机号必填!");
        }
        SysUser sysUser = sysUserService.selectUserByUserName(loginBody.getUsername());
        if (null == sysUser) {
            throw new UserNotExistsException();
        }
        AjaxResult ajax = AjaxResult.success();
        Map<String, String> code = new HashMap<>();
        int codeNumber = Integer.valueOf((String.valueOf(sysUser.getUserId()) + getCode2()));
        log.info("领导审核验证码是:{}", codeNumber);
        code.put("code", String.valueOf(codeNumber));
        sendSms.loginSendSms(loginBody.getLeaderUserName(), code, true);
        redisCache.setCacheObject(CacheConstants.LOGIN_SMS + loginBody.getLeaderUserName(), codeNumber, 300, TimeUnit.SECONDS);
        return ajax;
    }


    @PermitAll
    @PostMapping("/getSmsCode")
    public AjaxResult getSmsCode(@RequestBody LoginBody loginBody) throws ExecutionException, InterruptedException {
        if (StringUtils.isEmpty(loginBody.getUsername())) {
            throw new BaseException("手机号必填!");
        }
        SysUser sysUser = sysUserService.selectUserByUserName(loginBody.getUsername());
        if (null == sysUser) {
            throw new UserNotExistsException();
        }
        AjaxResult ajax = AjaxResult.success();
        Map<String, String> code = new HashMap<>();
        int codeNumber = getCode();
        code.put("code", String.valueOf(codeNumber));
        sendSms.loginSendSms(loginBody.getUsername(), code, false);
        redisCache.setCacheObject(CacheConstants.LOGIN_SMS + loginBody.getUsername(), codeNumber, 300, TimeUnit.SECONDS);
        return ajax;
    }


    /**
     * 获取用户信息
     *
     * @return 用户信息
     */
    @GetMapping("getInfo")
    public AjaxResult getInfo() {
        LoginUser loginUser = SecurityUtils.getLoginUser();
        SysUser user = loginUser.getUser();
        Set<String> roles = permissionService.getRolePermission(user);
        Set<String> permissions = permissionService.getMenuPermission(user);
        if (!loginUser.getPermissions().equals(permissions)) {
            loginUser.setPermissions(permissions);
            tokenService.refreshToken(loginUser);
        }
        AjaxResult ajax = AjaxResult.success();
        ajax.put("user", user);
        ajax.put("roles", roles);
        if (null != user.getRoles()) {
            String roleName = user.getRoles().stream().map(role -> role.getRoleName()).distinct().collect(Collectors.joining("_"));
            user.setRoleName(roleName);
        }
        ajax.put("permissions", permissions);
        return ajax;
    }

    /**
     * 获取路由信息
     *
     * @return 路由信息
     */
    @GetMapping("getRouters")
    public AjaxResult getRouters() {
        Long userId = SecurityUtils.getUserId();
        List<SysMenu> menus = menuService.selectMenuTreeByUserId(userId);
        return AjaxResult.success(menuService.buildMenus(menus));
    }
}
